package org.shoukaiseki.common.utils;

import java.math.BigDecimal;

/**
 * 为运算工具包
 * org.shoukaiseki.common.utils.BitOperationUtils
 * <br>
 *
 * @author shoukaiseki ブログ http://www.shoukaiseki.top/<br> E-メール jiang28555@Gmail.com<br>
 * @date 2021-03-09 23:54:03<br>
 */
public class BitOperationUtils {


    /**
     * 与运算
     * @param num1      为null当作0处理
     * @param num2      为null当作0处理
     * @return          num1&mun2
     */
    public static int bitAndNumber(Integer num1,Integer num2){
        if (num1==null||num2==null) {
            return 0;
        }
        return num1&num2;
    }



    /**
     * 或运算
     * @param num1      为null当作0处理
     * @param num2      为null当作0处理
     * @return          num1|mun2
     */
    public static long bitOrNumberToLong(Number num1,Number num2){
        if (num1==null) {
            return num2==null?0:num2.longValue();
        }
        if(num2==null){
            return num1.longValue();
        }
        return num1.longValue()|num2.longValue();
    }


    /**
     * 或运算
     * @param num1      为null当作0处理
     * @param num2      为null当作0处理
     * @return          num1|mun2
     */
    public static int bitOrNumber(Integer num1,Integer num2){
        if (num1==null) {
            return num2==null?0:num2;
        }
        if(num2==null){
            return num1;
        }
        return num1|num2;
    }


    /**
     * 与运算判断
     * @param num1      为null当作0处理
     * @param num2      为null当作0处理
     * @return          true:两数相与等于num2,false:相与为0,或不为 num2
     */
    public static boolean isBitAndNumber(Integer num1,Integer num2){
        if(num1==null||num2==null){
            return false;
        }
        return (num1&num2)==num2;
    }

    /**
     * 与运算判断
     * @param num1      为null当作0处理
     * @param num2s      为null当作0处理
     * @return          true:num1 与 num2s数组中任何一个相与都大于0;
     * {@code            (num1&num2s[0]>0)&&(num1&num2s[1]>0)&&(num1&num2s[2]>0)
     * }
     */
    public static boolean allBitAndNumbers(Integer num1,Integer... num2s){
        if(num1==null||num2s==null){
            return false;
        }
        Integer tmp=0;
        for (Integer num2Tmp : num2s) {
            tmp|=num2Tmp;
        }
        // (num1&4>0)&&(num1&8>0)&&(num1&1>0)
        // (num1&13)==13
        // (num1&(1|4|8))==(1|4|8)
        // 三中方式结果相同

        return (num1&tmp)==tmp;
    }

    /**
     * 判断指定位是否为1
     * @param num1
     * @param bitIndex
     * @return
     */
    public static boolean specifiedBitIsOne(Integer num1,int bitIndex){
        if(num1==null){
            return false;
        }
        return (num1& (1 << (bitIndex-1)))>0;
    }


    /**
     *  根据条件设置指定位是 清零还是置位
     * @param condition         条件
     * @param value      要改变的值
     * @param bitIndex   位索引 (1-31),int类型最多31位,,最高位为+-的补位
     * @return      condition=true: bit|value       value 对应位置位
     *              condition=false: bit&(~value)      value 对应位清零
     */
    public static int specifiedBitTrueSetbFalseClr(boolean condition,Integer value,int bitIndex){
        if(value==null){
            return condition?bitIndex:0;
        }
        if(condition){
            return value |= (1 << (bitIndex-1));
        }
        return value &= ~(1 << (bitIndex-1));
    }

    /**
     * 指定位置位(指定位设置为1)
     * 如汇编指令:SETB
     *
     * @param value      要改变的值
     * @param bitIndex   位索引 (1-31),int类型最多31位,,最高位为+-的补位
     * @return
     */
    public static int setbSpecifiedBitTo1(Integer value, int bitIndex) {
        if (value==null) {
            return (1 << (bitIndex-1));
        }
        return value |= (1 << (bitIndex-1));
    }

    /**
     * 指定位清零
     * 汇编指令:CLR
     *
     * @param value      要改变的值
     * @param bitIndex   位索引 (1-31),int类型最多31位,,最高位为+-的补位
     * @return
     */
    public static Integer clrSpecifiedBitTo0(Integer value, int bitIndex) {
        if (value==null) {
            return 0;
        }
        return value &= ~(1 << (bitIndex-1));
    }

    /**
     * 指定位取反
     * 取反:CPL,异或:XRL
     *
     * @param value      要改变的值
     * @param bitIndex   位索引 (1-31),int类型最多31位,,最高位为+-的补位
     * @return
     */
    public static Integer xrlSpecifiedBitToReverse(Integer value, int bitIndex) {
        if(value==null){
            return 0 ^ (1 << (bitIndex - 1));
        }
        return value ^= (1 << (bitIndex-1));
    }


}
